#ifndef PRNGD_H_
#define PRNGD_H_

typedef enum { INIT_ST, LOCAL_ST, TCP_ST, UDP_ST, DM_ST, MQ_ST}Prngd_State;


#include <iostream>
#include <fstream>
#include "stdio.h"
#include "signal.h"

#include <gmp.h>
#include <gmpxx.h>
#include "IOUnit.h"


#define PRNGD_NONE 0
#define PRNGD_BBS 1
#define PRNGD_ELSE 2
#define PRNGD_FBBS 3

#define OUTPUT_STDFILE "prngd_out"
#define random_file "/dev/random"
#define u_random_file "/dev/urandom"

static const int LOCAL_CODE = 0x01;
static const int TCP_CODE = 0x02;
static const int UDP_CODE = 0x04;
static const int UDOMAIN_CODE = 0x08;
static const int MQ_CODE = 0x10;



//#define DEBUG_MODE
class BBS;


/**
\class Prngd
\brief Can generate random bits with the help of a BBS-generator or a ......

Prngd uses a specific command line input to operate.
Example: -o prngd_out -bbs 1024 -s 123456

The random bits will be stored in the file prngd_out (-o prngd_out)
Prngd will generate 1025 pseudo random bits using a Blum Blum Shub generator. (-bbs 1024)
Prngd will use the number 123456 to COMPUTE the initial seed for the generator. 123456 IS NOT the seed !. (-s 123456)
*/
class Prngd
{

	public:

		/**Constructor*/
		Prngd(Prngd_State state);
		/**Destructor*/
		~Prngd();


		/** Main function of the prngd. Following steps will be executed:
		 - Read all parameters from command line.
		 - Generate the seed.
		 - Generate the random bits with the selected generator.
		 - Write the random bits to an output file.
		 \param argc The number of parameters.
		 \param argv Two dimensional array of char with all the parameters.
		 \return 0 if the parameters are valid or -1 if something is not ok.*/
		char* work(int param_count, char** params);


		/** Using dev/random for linux or Crypt API for Windows, to generate random data.
		\param numberOfByte The value of how many bytes to generate.*/
		static char* getRndData(int numberOfBits, bool useRandom);


		/** After the generation of random bits you can use this function to get the size of the result in bytes.
		\return The size ot the result in bytes.*/
		int getResultSize()
		{
			return(bitCount / 8 + bitCount % 8);
		}

	private:

		/** It it is set to true, the generator will try to use /dev/random otherwise it will always use /dev/urandom.*/
		bool useRandom;
		/** Switch to select which generator should be used, constants are defined at Prngd.h.*/
		short prngd_switch; 
		/**Variable s2 as a char Array.*/
		char* seed_part2;
		/** Helps us to decide what we do with the output data (local writes it into a file, tcp will send it through the socket to the client)*/
		int state;
		/** The number of random bits.*/
		int bitCount;
		/** Path and or file name of the file where the generated bits are saved to.*/
		std::string* output_file; 
		/**Object of the BBS generator.*/
		BBS* bbs;
		/**Object to read from or write to binary files.*/
		IOUnit* iounit; 
		/** First it's the user input, some time later it will be the generator seed.*/
		mpz_t s; 
		/** A second part of the seed, that will be linked to the user input with a xor-operation.*/
		mpz_t s2; 
		/** At the end it will have all generated random bits as one big integer.*/
		mpz_t output_bits;


		/** Starts reading the command line parameters and filling our private variables.
		 \param argc The number of parameters.
		 \param argv Two dimensional array of char with all the parameters.
		 \return 0 if the parameters are valid or -1 if something is not ok.*/
		int readParameters(int param_count, char** params);
};
#endif
